// Project 5: Lexer Module
// 4.1.08

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lexer.h"

void lex(FILE *err, char s[], int ln, struct vm_State *ll)
{
       char* tok;
       // intial tokenize of the string & call function to indentify the token
       tok = strtok(s, " ");  
        while(tok != NULL) // loop for the rest of the tokens in the string
        {
			if(strcmp(tok, "#") != 0)
			{
                validate(err, ll, tok, ln);
                tok = strtok(NULL, " ");
            }
			else
				break;
        }
}

void validate(FILE *err, struct vm_State *ll, char t[], int ln) // check each token
{

       union value val;
       int type; // int = 1 ; float = 2 ; reg = 3 ; op = 4
       
       if (isFloat(t) == 1) // check if token is a float
       {
               val.f = atof(t);
               type = 2;
               list_pushback(ll, val, type, ln);
       }
       
       else if (isReg(t) == 1) //  check if token is valid register
       {
               if ( strcmp(t, "R0") == 0) {val.i = 0;}
               if ( strcmp(t, "R1") == 0) {val.i = 1;}
               if ( strcmp(t, "R2") == 0) {val.i = 2;}
               if ( strcmp(t, "R3") == 0) {val.i = 3;}
               if ( strcmp(t, "R4") == 0) {val.i = 4;}
               if ( strcmp(t, "R5") == 0) {val.i = 5;}
               if ( strcmp(t, "R6") == 0) {val.i = 6;}
               if ( strcmp(t, "R7") == 0) {val.i = 7;}
               if ( strcmp(t, "R8") == 0) {val.i = 8;}
               if ( strcmp(t, "R9") == 0) {val.i = 9;}
               type = 3;
               list_pushback(ll, val, type, ln);
       }
      
       else if (isOp(t) == 1) // check if token is valid opcode
       {
				// List: begin, end, move, add, sub, mult, divd, swap, copy, clr, dispr, disps, get, comp, loop
               if ( strcmp(t, "BEGIN") == 0) {val.op = BEGIN;}
               if ( strcmp(t, "END") == 0) {val.op = END;}
               if ( strcmp(t, "MOV") == 0) {val.op = MOV;}
               if ( strcmp(t, "ADD") == 0) {val.op = ADD;}
               if ( strcmp(t, "SUB") == 0) {val.op = SUB;}
               if ( strcmp(t, "MULT") == 0) {val.op = MULT;}
               if ( strcmp(t, "DIVD") == 0) {val.op = DIVD;}
               if ( strcmp(t, "SWAP") == 0) {val.op = SWAP;}
               if ( strcmp(t, "COPY") == 0) {val.op = COPY;}
               if ( strcmp(t, "CLR") == 0) {val.op = CLR;}
               if ( strcmp(t, "DISPR") == 0) {val.op = DISPR;}
               if ( strcmp(t, "GET") == 0) {val.op = GET;}
               if ( strcmp(t, "LOOP") == 0) {val.op = LOOP;}
               if ( strcmp(t, "COMP") == 0) {val.op = COMP;}
               type = 4;
               list_pushback(ll, val, type, ln);
       }   
       else // invalid print info to stderr
       {      
               // use token & line number and print error
               fprintf (err, "L%d: INVALID: %s\n", ln , t);
       }
}

int isInt(char t[])  // checks if valid Integer
{
       int i;
       int r = 1;  // starts as true(1)
       
       for (i=0 ; i < strlen(t); i++)
       {
               // if there is a period, then false
               if ( t[i] == '.' )
               { r = 0; }
               
               // all chars are digits or "-" sign or false
               if ( ( isdigit(t[i]) == 0) && ( t[i] != '-') && ( t[i] != '\0') )
               { r = 0; }
               
               // if "-" sign, must be first char or false
               if ( t[i] == '-')
               {
                       if (i != 0)
                       { r = 0; }
               }
       }
       
       return r;
}

int isFloat(char t[])  // checks if valid Float
{
       int i, test = 0;
       int r = 1;  // starts as true (1)
       
       for (i=0 ; i < strlen(t); i++)
       {
       
               // all chars are digits or "-" sign or "." period or
               if ( ( isdigit(t[i]) == 0) && ( t[i] != '-') && ( t[i] != '.') && ( t[i] != '\0') )
               { r = 0; }
               
               // if "-" sign, must be first char
               if ( t[i] == '-')
               {
                       if (i != 0)
                       { r = 0; }
               }

               // if "." sign counts them up
               if ( t[i] == '.')
               {
                       test++;
               }
               
               // cant have more than one period
               if ( test > 1 )
               { r = 0; }
       }
       
       return r;
}

int isReg(char t[]) // checks if valid Register
{
       int i;
       int r = 1;  // starts as true (1)
       
       if ( strcmp(t, "R0") !=0 && strcmp(t, "R1") !=0 && strcmp(t, "R2") !=0 && strcmp(t, "R3") !=0 && strcmp(t, "R4") !=0 && strcmp(t, "R5") !=0 && strcmp(t, "R6") !=0 && strcmp(t, "R7") !=0 && strcmp(t, "R8") !=0 && strcmp(t, "R9") !=0 )
       { r = 0; }
       
       return r;
}

int isOp(char t[]) // checks if valid Opcode
{
       int i;
       int r = 1;  // starts as true (0)
       
       if ( strcmp(t, "BEGIN") != 0 && strcmp(t, "END") != 0 && strcmp(t, "MOV") != 0 && strcmp(t, "ADD") != 0 && strcmp(t, "SUB") != 0 && strcmp(t, "MULT") != 0 && strcmp(t, "DIVD") != 0 && strcmp(t, "SWAP") != 0 && strcmp(t, "COPY") != 0 && strcmp(t, "CLR") != 0 && strcmp(t, "DISPR") != 0 && strcmp(t, "GET") != 0 && strcmp(t, "COMP") != 0 && strcmp(t, "LOOP") != 0 )
       { r = 0; }
       
       return r;
}
